#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
按键检测和摄像头读取程序 - 精简版
"""

import os
import struct
import time
import cv2
import subprocess

class KeyCameraCapture:
    def __init__(self):
        self.running = False
        self.event_fd = None
        self.cap = None
        self.setup_camera()
    
    def setup_camera(self):
        """设置摄像头参数"""
        print("设置摄像头参数...")
        try:
            # 设置格式
            subprocess.run(['v4l2-ctl', '-d', '/dev/video11', '--set-fmt-video=width=480,height=480,pixelformat=NV12'], 
                         capture_output=True, timeout=1)
            # 设置曝光和增益
            subprocess.run(['v4l2-ctl', '-d', '/dev/v4l-subdev3', '--set-ctrl', 'exposure=24,analogue_gain=248'], 
                         capture_output=True, timeout=1)
            # 打开摄像头
            self.cap = cv2.VideoCapture('/dev/video11')
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
            # 设置OpenCV超时参数
            self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)  # 减少缓冲区大小
            self.cap.set(cv2.CAP_PROP_FPS, 30)  # 设置帧率
            
            # 检查摄像头是否成功打开
            if not self.cap.isOpened():
                print("摄像头打开失败")
                return
            else:
                print("摄像头打开成功")
            
            print("摄像头设置完成")
        except Exception as e:
            print(f"设置失败: {e}")
    
    def read_frame(self):
        """读取一帧图像"""
        try:
            if not self.cap.isOpened():
                print("摄像头未打开")
                return
            
            # 按键后等待5毫秒再读取
            time.sleep(0.005)  # 5毫秒
            
            # 使用非阻塞方式读取，设置超时
            import threading
            import queue
            
            result_queue = queue.Queue()
            
            def read_frame_worker():
                try:
                    # 抛弃第一帧，直接读取第二帧
                    self.cap.read()  # 抛弃第一帧
                    # 读取第二帧
                    ret, frame = self.cap.read()
                    result_queue.put((ret, frame))
                except Exception as e:
                    result_queue.put((False, None))
            
            # 启动读取线程，设置1秒超时
            read_thread = threading.Thread(target=read_frame_worker)
            read_thread.daemon = True
            read_thread.start()
            read_thread.join(timeout=1.0)  # 1秒超时
            
            if read_thread.is_alive():
                print("读取超时，中断操作")
                return
            
            if result_queue.empty():
                print("读取失败")
                return
                
            ret, frame = result_queue.get()
            
            if ret and frame is not None:
                timestamp = int(time.time())
                output_file = f"captured_frame_{timestamp}.raw"
                
                # 转换为RGB并保存
                rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                with open(output_file, 'wb') as f:
                    f.write(rgb.tobytes())
                
                print(f"图像已保存: {output_file} ({len(rgb.tobytes())} bytes)")
            else:
                print("读取图像失败")
                    
        except Exception as e:
            print(f"读取图像失败: {e}")
    
    def open_event_device(self):
        """打开按键设备"""
        try:
            self.event_fd = os.open('/dev/input/event4', os.O_RDONLY | os.O_NONBLOCK)
            return True
        except Exception as e:
            print(f"打开设备失败: {e}")
            return False
    
    def process_key_event(self, event_data):
        """处理按键事件"""
        if len(event_data) >= 24:
            data_bytes = event_data[16:24]
            if data_bytes.hex() == "0100bf0001000000":
                print("按键按下！开始读取图像...")
                self.read_frame()
    
    def start_monitoring(self):
        """开始监听按键"""
        if not self.open_event_device():
            return
        
        print("开始监听按键事件，按Ctrl+C停止")
        print("等待按键按下时读取图像...")
        self.running = True
        
        try:
            while self.running:
                try:
                    event_data = os.read(self.event_fd, 24)
                    if event_data:
                        self.process_key_event(event_data)
                except OSError:
                    time.sleep(0.1)
                    continue
        except KeyboardInterrupt:
            print("\n收到停止信号")
        finally:
            self.running = False
            if self.event_fd:
                os.close(self.event_fd)
            if self.cap:
                self.cap.release()

def main():
    print("按键检测和摄像头读取程序")
    print("=" * 40)
    capture = KeyCameraCapture()
    capture.start_monitoring()

if __name__ == "__main__":
    main()
